const util = require('util');
const debug = util.debuglog('oil-game:login:remote');

var consts = require('../../../util/consts');
var utils = require('../../../util/utils');
var time = require('../../../util/time');
var pushUtils = require('../../../util/pushUtils');
var User = require('../lib/userSchema');
var logger = require('pomelo-logger').getLogger('login-Remote', 'loginRemote');
var oilLog = require('../../../domain/oilLog');
var moneyLog = require('../../../domain/moneyLog');
var uuid = require('node-uuid');

const {
    getUserByMongo,   //从Mogo中查询用户信息
    sonList, //查询徒弟信息
    grandSonList, //徒孙信息
    addApprenticeOil, //增加徒弟石油贡献
    addDiscipleOil, //增加徒孙石油贡献
    getUserMoneyAndOil,
    getTotalOil,
    getParentByUid,
    getUserGradeLimit,    //获取用户等级限制
    getTotalWithdrawByUid,
} = require('../lib/dao');

const {formatCoins} = require('../../upgrade/lib/action');
const {default: BigNumber} = require('bignumber.js');

module.exports = function (app) {
    return new Handler(app);
};
var Handler = function (app) {
    this.app = app;
};
var handler = Handler.prototype;

// 用户离线
handler.userLeave = function (uid, frontendId, cb) {
    var user = this.app.loginService.getUser(uid);
    if (!user) return;
    //保存用户信息
    user.immediatelySave();
    //更新用户地图信息
    user.updateMap();
    // 更新开启宝箱信息
    user.chestSave();
    // 同步宝箱信息
    user.syncBox();
    //更新用户交易所信息
    user.exchangeSave();
    //更新用户石油交易所信息
    user.exchangeEssenceSave();
    //更新用户升级信息
    user.upgradeSave();
    //更新用户签到信息
    user.signInSave();
    //更新用户幸运抽奖信息
    user.luckDrawSave();
    //清空内存
    this.app.loginService.removeUser(uid);
    utils.invokeCallback(cb);
};

// 更新新注册用户的师傅用户的数据
handler.addApprentice = function (uid, frontendId, cb) {
    var self = this;
    var user = this.app.loginService.getUser(uid);
    if (!user) {
        // 不在线 更新数据库
        User.findOne({uid: uid}, function (err, data) {
            if (err) {
                cb(err, null);
                return err;
            }
            if (data) {
                data.apprentice_num += 1;
                if (!data.is_effect_user) {
                    //重新判断是否为有效用户
                    data.is_effect_user = utils.isEffectUser(data);
                }
                User.updateOne({uid: uid}, data, function (err, data) {
                    if (err) {
                        cb(err, null);
                        return err;
                    }
                    cb(null, data);
                });
            } else {
                cb(err, null);
            }
        });
    } else {
        // 在线 更新内存
        user.apprentice_num += 1;
        if (!user.is_effect_user) {
            //重新判断是否为有效用户
            user.is_effect_user = utils.isEffectUser(user);
        }
        // 推送徒弟数据
        pushUtils.onApprenticeAdd(self.app, {apprentice_num: user.apprentice_num}, uid, frontendId);
        //如果达到领取红包条件发送推送
        if (utils.canReceiveRed(user)) {
            pushUtils.onRedPacketChange2(self.app, {canReceive: true}, uid, frontendId);
        }
    }
    utils.invokeCallback(cb);
};

// 更新新注册用户的师爷用户的数据
handler.addDisciple = function (uid, frontendId, cb) {
    var self = this;
    var user = this.app.loginService.getUser(uid);
    if (!user) {
        // 不在线 更新数据库
        User.findOne({uid: uid}, function (err, data) {
            if (err) {
                cb(err, null);
                return err;
            }
            if (data) {
                data.disciple_num += 1;
                User.updateOne({uid: uid}, data, function (err, data) {
                    if (err) {
                        cb(err, null);
                        return err;
                    }
                    cb(null, data);
                });
            } else {
                cb(err, null);
            }
        });
    } else {
        // 在线 更新内存
        user.disciple_num += 1;
        // 推送徒孙数据
        pushUtils.onDiscipleAdd(self.app, {disciple_num: user.disciple_num}, uid, frontendId);
        //如果达到领取红包条件发送推送
        if (utils.canReceiveRed(user)) {
            pushUtils.onRedPacketChange2(self.app, {canReceive: true}, uid, frontendId);
        }
    }
    utils.invokeCallback(cb);
};

handler.getUser = function (uid, cb) {
    var user = this.app.loginService.getUser(uid);
    cb(null, user);
};

handler.getAllUsers = function (obj, cb) {
    var users = this.app.loginService.getUserList();
    cb(null, users);
};

handler.setUser = function (user, cb) {
    if (user) {
        var currentUser = this.app.loginService.getUser(user.uid);
        for (var key in user) {
            if (key.startsWith('_')) {
                continue
            }
            currentUser[key] = user[key];
        }
        cb(null, currentUser);
    } else {
        cb(consts.Msg.USER_NOT_FOUND, null);
    }
};

/**
 * 关闭双倍产金奖励
 * @param uid
 * @param frontendId
 * @param cb
 */
handler.closeDoubleEarning = function (uid, frontendId, cb) {
    var self = this;
    var user = this.app.loginService.getUser(uid);

    if (user.isDouble) {
        user.isDouble = false;
        let totalPro = utils.calTotalProduction(user.levelInfo);
        //秒产金量增加消息推送
        self.app.get('channelService').pushMessageByUids(consts.PushRoute.PRODUCT_COINS_CHANGE, {
            product: utils.formatCoins(totalPro),
            offline: utils.formatCoins(totalPro / 10),
            action: 'reduce',
            type: 'normal'
        }, [{
            uid: uid,
            sid: frontendId
        }]);
    }

    utils.invokeCallback(cb);
}

/**
 * 领取抽奖奖励
 * @param uid
 * @param frontendId
 * @param reward
 * @param cb
 */
handler.receiveLottery = function (uid, frontendId, reward, cb) {
    var self = this;
    var user = this.app.loginService.getUser(uid);
    if (user) {
        //获取当前总产金量
        let totalPro = utils.calTotalProduction(user.levelInfo);
        if (reward.value == 'no1') { //大量金币
            totalPro = totalPro * 3000;
            //徒弟助力金币加成
            utils.apprenticeHelpNum(uid, function (err, num) {
                //无异常、且助力加成大于0
                if (!err && num > 0) {
                    let help = parseFloat((num / 100).toFixed(2));
                    totalPro = totalPro + totalPro * help;
                }
                user.coins = parseFloat(user.coins) + totalPro;
                //金币增加消息推送
                self.app.get('channelService').pushMessageByUids(consts.PushRoute.COINS_INCREASE, {
                    increase: utils.formatCoins(totalPro),
                    current: utils.formatCoins(user.coins)
                }, [{
                    uid: uid,
                    sid: frontendId
                }], null, function (err) {
                    if (!!err) {
                        logger.error("err: ", err)
                    }
                });
            });
        } else if (reward.value == 'no2') { //海量金币
            totalPro = totalPro * 5000;
            //徒弟助力金币加成
            utils.apprenticeHelpNum(uid, function (err, num) {
                //无异常、且助力加成大于0
                if (!err && num > 0) {
                    let help = parseFloat((num / 100).toFixed(2));
                    totalPro = totalPro + totalPro * help;
                }
                user.coins = parseFloat(user.coins) + totalPro;
                //金币增加消息推送
                self.app.get('channelService').pushMessageByUids(consts.PushRoute.COINS_INCREASE, {
                    increase: utils.formatCoins(totalPro),
                    current: utils.formatCoins(user.coins)
                }, [{
                    uid: uid,
                    sid: frontendId
                }], null, function (err) {
                    if (!!err) {
                        logger.error("err: ", err)
                    }
                });
            });
        } else if (reward.value == 'no3') { //中量金币
            totalPro = totalPro * 2000;
            //徒弟助力金币加成
            utils.apprenticeHelpNum(uid, function (err, num) {
                //无异常、且助力加成大于0
                if (!err && num > 0) {
                    let help = parseFloat((num / 100).toFixed(2));
                    totalPro = totalPro + totalPro * help;
                }
                user.coins = parseFloat(user.coins) + totalPro;
                //金币增加消息推送
                self.app.get('channelService').pushMessageByUids(consts.PushRoute.COINS_INCREASE, {
                    increase: utils.formatCoins(totalPro),
                    current: utils.formatCoins(user.coins)
                }, [{
                    uid: uid,
                    sid: frontendId
                }], null, function (err) {
                    if (!!err) {
                        logger.error("err: ", err)
                    }
                });
            });
        } else if (reward.value == 'no4') { //加速3分钟
            user.isDouble = true;
            user.beginDouble = time.currentUnix();
            //秒产金量增加消息推送
            self.app.get('channelService').pushMessageByUids(consts.PushRoute.PRODUCT_COINS_CHANGE, {
                product: utils.formatCoins(totalPro * 2),
                action: 'add',
                type: 'double'
            }, [{
                uid: uid,
                sid: frontendId
            }]);
        } else if (reward.value == 'no5') { //少量金币
            totalPro = totalPro * 1500;
            //徒弟助力金币加成
            utils.apprenticeHelpNum(uid, function (err, num) {
                //无异常、且助力加成大于0
                if (!err && num > 0) {
                    let help = parseFloat((num / 100).toFixed(2));
                    totalPro = totalPro + totalPro * help;
                }
                user.coins = parseFloat(user.coins) + totalPro;
                //金币增加消息推送
                self.app.get('channelService').pushMessageByUids(consts.PushRoute.COINS_INCREASE, {
                    increase: utils.formatCoins(totalPro),
                    current: utils.formatCoins(user.coins)
                }, [{
                    uid: uid,
                    sid: frontendId
                }], null, function (err) {
                    if (!!err) {
                        logger.error("err: ", err)
                    }
                });
            });
        } else if (reward.value == 'no6') { //抽奖券x2
            user.luck_draw_num = parseInt(user.luck_draw_num) + 2;
        }
        //抽奖完成消耗一张抽奖券
        user.luck_draw_num = (parseInt(user.luck_draw_num) - 1) >= 0 ? parseInt(user.luck_draw_num) - 1 : 0;
        //抽奖券变更提醒
        self.app.get('channelService').pushMessageByUids(consts.PushRoute.LOTTERY_TICKET_CHANGE, {
            current: user.luck_draw_num
        }, [{
            uid: uid,
            sid: frontendId
        }], null, function (err) {
            if (!!err) {
                logger.error("err: ", err)
            }
        });
    }

    utils.invokeCallback(cb);
}

/**
 * 增加金钱
 * @param uid 用户ID
 * @param frontendId 前端ID
 * @param money 增加金钱
 * @param src 来源
 * @param cb 回调函数
 */
handler.addMoney = function (uid, frontendId, money, src, cb) {
    var self = this;
    var user = this.app.loginService.getUser(uid);
    if (user && money > 0) {
        user.money = parseFloat(user.money) + money;
        user.total_money = parseFloat(user.total_money) + money;
    }
    //更新mysql
    let mysqlClient = this.app.get('mysqlClient'); //获取全局mysql client
    let sql = `update user_info set money=money+?,total_money=total_money+? where uid=?`;
    let args = [money, money, uid];
    mysqlClient.query(sql, args, function (err, res) {
        if (err) {
            //执行失败，回滚
            user.money -= money;
            user.total_money -= money;
            let err_msg = 'update mysql err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    });
    //加到金钱详情中
    let MoneyLog = new moneyLog({
        id: uuid.v4(),
        uid: uid,
        increase_money: money,
        total_money: user.total_money,
        money: user.money,
        operate: money >= 0 ? "add" : "sub",
        type: src,
        gmt_create: new Date().valueOf(),
        gmt_modified: new Date().valueOf()
    })
    MoneyLog.save(MoneyLog, function (err, data) {
        if (!!err) {
            user.money -= money;
            user.total_money -= money;

            let err_msg = 'addMoney err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    });

    pushUtils.onMoneyAdd(self.app, {increase: money, current: user.money.toFixed(2)}, uid, frontendId);
    utils.invokeCallback(cb);
};

/**
 * 金钱减少
 * @param uid
 * @param frontendId
 * @param money
 * @param cb
 */
handler.reduceMoney = function (uid, frontendId, money, current_money, cb) {
    let self = this;
    //更新mysql
    let mysqlClient = this.app.get('mysqlClient'); //获取全局mysql client
    let sql = `update user_info set money = ? where uid=?`;
    let args = [current_money, uid];
    mysqlClient.query(sql, args, function (err, res) {
        if (err) {
            //执行失败，回滚
            let err_msg = 'update mysql err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    });
    pushUtils.onMoneyReduce(self.app, {increase: money, current: current_money.toFixed(2)}, uid, frontendId);
    utils.invokeCallback(cb);
}

/**
 * 增加金币
 * @param {*} uid
 * @param {*} frontendId
 * @param {*} coinsAddNum 增加数额
 * @param {*} cb
 * @param {*} isPush 是否需要推送给客户端
 */
handler.addCoins = async function (uid, frontendId, coinsAddNum, isPush = false, cb) {
    if (typeof coinsAddNum != "number") {
        console.warn("coinsAddNum is not a number");
        coinsAddNum = Number(coinsAddNum);
    }
    let user = this.app.loginService.getUser(uid);
    if (!user) {
        utils.invokeCallback(cb);
        return;
    }
    let self = this;
    let newCoins = new BigNumber(user.coins).plus(new BigNumber(coinsAddNum));
    user.coins = newCoins.toFormat(0).replace(/[,]/ig, "");
    // console.log(user);
    self.app.loginService.setUser(user);

    if (isPush) {
        pushUtils.onCoinsAdd(self.app, {
            increase: formatCoins(BigNumber(coinsAddNum)),
            current: formatCoins(BigNumber(user.coins))
        }, uid, frontendId);
    }
    utils.invokeCallback(cb);
}

/**
 * 减少金币
 * @param uid
 * @param frontendId
 * @param coins
 * @param cb
 * @returns {Promise<void>}
 */
handler.reduceCoins = async function (uid, frontendId, coins, cb) {
    if (typeof coinsAddNum != "number") {
        console.warn("coinsAddNum is not a number");
        coins = Number(coins);
    }
    let user = this.app.loginService.getUser(uid);
    let self = this;
    user.coins = new BigNumber(user.coins).minus(new BigNumber(coins));
    if (user.coins < 0) {
        user.coins = 0;
    }
    this.app.loginService.setUser(user);
    pushUtils.onCoinsReduce(self.app, {
        increase: formatCoins(BigNumber(coins)),
        current: formatCoins(BigNumber(user.coins))
    }, uid, frontendId);
    utils.invokeCallback(cb);
}

/**
 * 关闭双倍奖励
 * @param uid
 * @param frontendId
 * @param cb
 * @returns {Promise<void>}
 */
handler.closeDoubleReward = async function (uid, frontendId, cb) {
    let self = this;
    pushUtils.onDoubleRewardClose(self.app, {}, uid, frontendId);
    let user = self.app.loginService.getUser(uid);
    if (user && user.levelInfo) {
        let product = 0;
        for (let i = 0; i < user.levelInfo.length; i++) {
            product += user.levelInfo[i]['product'];
        }
        pushUtils.onProductChange(self.app, {
            product: formatCoins(BigNumber(product))
        }, uid, frontendId);
        pushUtils.onDoubleRewardClose(self.app, {
            product: formatCoins(BigNumber(product))
        }, uid, frontendId);
    }
    utils.invokeCallback(cb);
}

/**
 * 查询父用户信息
 * @param uid
 * @param frontendId
 * @param cb
 * @returns {Promise<unknown>}
 */
handler.getParentUser = async function (uid, frontendId, cb) {
    let userInfo = await getParentByUid.call(this, uid);
    cb(null, userInfo);
}

/**
 * 增加石油
 * @param {*} uid
 * @param {*} frontendId session.frontendId
 * @param {*} oilAddNum 增加数量
 * @param {*} src 来源
 * @param {*} extend 扩展信息
 * @param {*} cb
 */
handler.addOil = function (uid, frontendId, oilAddNum, src, extend, cb) {
    if (typeof oilAddNum != "number") {
        console.warn("oilAddNum is not a number");
        oilAddNum = Number(oilAddNum);
    }
    let self = this;
    let user = this.app.loginService.getUser(uid);
    user.oil += oilAddNum;
    if (user.oil < 0) {
        oilAddNum -= user.oil;
        user.oil = 0;
    }
    if (oilAddNum > 0) {
        user.total_oil += oilAddNum;
    }

    //加到石油详情中
    var OilLog = new oilLog({
        id: uuid.v4(),
        uid: uid,
        increase_oil: oilAddNum,
        total_oil: user.oil,
        operate: oilAddNum >= 0 ? "add" : "sub",
        gmt_create: new Date().valueOf(),
        time: time.todayZeroClockUnix(),
        type: src,
        extend: extend
    })
    OilLog.save(OilLog, function (err, data) {
        if (!!err) {
            let err_msg = 'addOil err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    })
    //更新mysql
    let mysqlClient = this.app.get('mysqlClient');//获取全局mysql client
    let sql = `update user_info set oil=oil+?,total_oil=total_oil+? where uid=?`
    let args = [oilAddNum, oilAddNum, uid]
    if (oilAddNum < 0) {
        sql = `update user_info set oil=oil+? where uid=?`
        args = [oilAddNum, uid]
    }
    mysqlClient.query(sql, args, function (err, res) {
        if (err) {
            //执行失败, 回滚石油
            user.oil -= oilAddNum;
            let err_msg = 'update mysql err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    })
    //清空缓存
    var redis = self.app.get('redis');
    redis.del(consts.RedisPrefix.OIL_DETAIL_PREFIX + uid, function (err, data) {
    });
    pushUtils.onOilAdd(self.app, {increase: oilAddNum, current: Number(user.oil).toFixed(2)}, uid, frontendId);
    utils.invokeCallback(cb);
}

/**
 * 精华石油变更
 * @param uid
 * @param frontendId
 * @param oilNum
 * @param cb
 */
handler.addEssenceOil = function (uid, frontendId, oilAddNum, cb) {
    let self = this;
    if (typeof oilAddNum != "number") {
        oilAddNum = Number(oilAddNum);
    }
    let user = this.app.loginService.getUser(uid);
    user.essence_oil += oilAddNum;
    if (user.oil < 0) {
        oilAddNum -= user.essence_oil;
        user.oil = 0;
    }
    if (oilAddNum > 0) {
        user.total_essence_oil += oilAddNum;
    }
    //更新mysql
    let mysqlClient = this.app.get('mysqlClient');//获取全局mysql client
    let sql = `update user_info set essence_oil=essence_oil+?,total_essence_oil=total_essence_oil+? where uid=?`
    let args = [oilAddNum, oilAddNum, uid]
    if (oilAddNum < 0) {
        sql = `update user_info set essence_oil=essence_oil+? where uid=?`
        args = [oilAddNum, uid]
    }
    mysqlClient.query(sql, args, function (err, res) {
        if (err) {
            //执行失败, 回滚石油
            user.essence_oil -= oilAddNum;
            let err_msg = 'update mysql err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    });
    //消息推送
    pushUtils.onEssenceOilAdd(self.app, {
        increase: oilAddNum,
        current: Number(user.essence_oil).toFixed(2)
    }, uid, frontendId);
    utils.invokeCallback(cb);
}

/**
 * 修改离线玩家石油
 * @param {*} uid
 * @param {*} oilAddNum
 * @param {*} src
 * @param {*} cb
 */
handler.updateOffLineOil = function (user, frontendId, oilAddNum, src, extend, cb) {
    let uid = user.uid
    user.oil += oilAddNum;
    if (user.oil < 0) {
        oilAddNum -= user.oil;
        user.oil = 0;
    }
    if (oilAddNum > 0) {
        user.total_oil += oilAddNum;
    }
    //加到石油详情中
    var OilLog = new oilLog({
        id: uuid.v4(),
        uid: uid,
        increase_oil: oilAddNum,
        total_oil: user.oil,
        operate: oilAddNum >= 0 ? "add" : "sub",
        gmt_create: new Date().valueOf(),
        time: time.todayZeroClockUnix(),
        type: src,
        extend: extend
    })
    OilLog.save(OilLog, function (err, data) {
        if (!!err) {
            let err_msg = 'addOil err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    })
    //更新mysql
    let mysqlClient = this.app.get('mysqlClient');//获取全局mysql client
    let sql = `update user_info set oil=oil+?,total_oil=total_oil+? where uid=?`
    let args = [oilAddNum, oilAddNum, uid]
    if (oilAddNum < 0) {
        sql = `update user_info set oil=oil+? where uid=?`
        args = [oilAddNum, uid]
    }
    mysqlClient.query(sql, args, function (err, res) {
        if (err) {
            let err_msg = 'update mysql err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    })

    // console.warn("/////====>>>>onOilAdd推送",uid,frontendId)
    pushUtils.onOilAdd(this.app, {increase: oilAddNum, current: parseFloat(user.oil)}, uid, frontendId);
    utils.invokeCallback(cb);
}

/**
 * 石油减少
 * @param uid
 * @param frontendId
 * @param oilAddNum
 * @param src
 * @param cb
 */
handler.reduceOil = function (uid, frontendId, oilAddNum, src, cb) {
    if (typeof oilAddNum != "number") {
        console.warn("oilAddNum is not a number");
        oilAddNum = Number(oilAddNum);
    }
    let self = this;
    let user = this.app.loginService.getUser(uid);
    if (user.oil < oilAddNum) {
        utils.invokeCallback(cb, new Error("oil insufficient"), "oil insufficient");
        return;
    }
    user.oil = parseFloat(user.oil) - oilAddNum;
    //异常处理
    if (user.oil < 0) user.oil = 0;
    //加到石油详情中
    let OilLog = new oilLog({
        id: uuid.v4(),
        uid: uid,
        increase_oil: oilAddNum,
        total_oil: user.oil,
        operate: oilAddNum >= 0 ? "add" : "sub",
        type: src,
        time: time.todayZeroClockUnix(),
        gmt_create: new Date().valueOf(),
        gmt_modified: new Date().valueOf()
    })
    OilLog.save(OilLog, function (err, data) {
        if (!!err) {
            let err_msg = 'reduceOil err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    })
    //更新mysql
    let mysqlClient = self.app.get('mysqlClient');//获取全局mysql client
    let sql = `update user_info set oil = ? where uid = ?`;
    let args = [oilAddNum, uid];
    mysqlClient.query(sql, args, function (err, res) {
        if (err) {
            //执行失败, 回滚石油
            user.oil += oilAddNum;
            let err_msg = 'update mysql err :' + err;
            utils.invokeCallback(cb, err, err_msg);
            return;
        }
    });
    //清空缓存
    var redis = self.app.get('redis');
    redis.del(consts.RedisPrefix.OIL_DETAIL_PREFIX + uid, function (err, data) {
    });
    //消息推送
    pushUtils.onOilReduce(self.app, {increase: oilAddNum, current: user.oil.toFixed(2)}, uid, frontendId);
    utils.invokeCallback(cb);
}


//打开待领取宝箱
handler.openBox = function (uid, boxId, cb) {
    let user = this.app.loginService.getUser(uid);
    //删除内存中的元素
    for (let i = 0; i < user.openChestInfo.length; i++)
        if (user.openChestInfo[i].id == boxId) {
            user.openChestInfo.splice(i, 1);
            break;
        }

    utils.invokeCallback(cb);
}

/**
 * 获取父用户的父用户ID
 * @param uid
 * @param frontendId
 * @param cb
 * @returns {Promise<void>}
 */
handler.getParentParentUid = async function (uid, frontendId, cb) {
    let userInfo = await getUserByMongo.call(this, uid);
    if (userInfo) {
        utils.invokeCallback(cb, null, userInfo.parent_id);
        return;
    }
    utils.invokeCallback(cb, null, "0");
}

/**
 * 查询徒弟信息
 * @param uid
 * @param pageNum
 * @param cb
 * @returns {Promise<void>}
 */
handler.getUserSonList = async function (uid, pageNum, cb) {
    let users = await sonList.call(this, uid, pageNum);
    utils.invokeCallback(cb, null, users);
}

/**
 * 查询徒孙信息
 * @param uid
 * @param pageNum
 * @param cb
 * @returns {Promise<void>}
 */
handler.getGrandSonList = async function (uid, pageNum, cb) {
    let users = await grandSonList.call(this, uid, pageNum);
    utils.invokeCallback(cb, null, users);
}

/**
 * 增加徒弟石油贡献
 * @param uid
 * @param oilNum
 * @param cb
 * @returns {Promise<void>}
 */
handler.addUserApprenticeOil = async function (uid, oilNum, cb) {
    await addApprenticeOil.call(this, uid, oilNum);
    utils.invokeCallback(cb, null);
}

/**
 * 增加徒孙的石油贡献
 * @param uid
 * @param oilNum
 * @param cb
 * @returns {Promise<void>}
 */
handler.addUserDiscipleOil = async function (uid, oilNum, cb) {
    await addDiscipleOil.call(this, uid, oilNum);
    utils.invokeCallback(cb, null);
}

/**
 * 获取石油和金钱
 * @param uid
 * @param cb
 * @returns {Promise<void>}
 */
handler.userMoneyAndOil = async function (uid, cb) {
    let data = await getUserMoneyAndOil.call(this, uid);
    utils.invokeCallback(cb, null, data);
}

/**
 * 获取用户累积提现金额
 * @param uid
 * @param cb
 * @returns {Promise<void>}
 */
handler.getTotalWithdraw = async function (uid, cb) {
    let data = await getTotalWithdrawByUid.call(this, uid);
    utils.invokeCallback(cb, null, data);
}

/**
 * 获取全网的石油总量
 * @param cb
 * @returns {Promise<void>}
 */
handler.totalOil = async function (cb) {
    let data = await getTotalOil.call(this);
    utils.invokeCallback(cb, null, data)
}

//获取用户相关数据
handler.getUserData = function (uid, cb) {
    let {video_num, apprentice_num, disciple_num} = this.app.loginService.getUser(uid);
    utils.invokeCallback(cb, null, {video_num, apprentice_num, disciple_num});
}

//获取用户等级
handler.getUserGrade = async function (uid, cb) {
    try {
        //当前用户
        let user = this.app.loginService.getUser(uid);
        //未找到当前用户
        if (!user) return utils.invokeCallback(cb, new Error(NOR_SEARCH_USER));
        //当前用户徒子徒孙数
        let {apprentice_num, disciple_num} = user;
        //获取用户等级限制
        let userGradeLimit = await getUserGradeLimit.call(this, uid);

        //排序
        userGradeLimit = userGradeLimit.sort((item1, item2) => item2.apprentice - item1.apprentice);
        //计算当前等级
        let name = "";
        for (let i = 0; i < userGradeLimit.length; i++) {
            if (apprentice_num >= userGradeLimit[i].apprentice && disciple_num >= userGradeLimit[i].grandson) {
                name = userGradeLimit[i].name;
                break;
            }
        }
        debug("uid = %s 获取用户等级 %s", uid, name);
        utils.invokeCallback(cb, null, name);
    } catch (err) {
        console.error(err);
        return utils.invokeCallback(cb, err);
    }
}

//获取用户等级限制信息
handler.getUserGradeLimit = async function (uid, cb) {
    try {
        let userGradeLimit = await getUserGradeLimit.call(this, uid);
        debug("uid = %s 获取用户等级限制相关信息 %s", uid, JSON.stringify(userGradeLimit));
        utils.invokeCallback(cb, null, userGradeLimit);
    } catch (err) {
        console.error(err);
        return utils.invokeCallback(cb, err);
    }
}
